import axios, { AxiosError, type AxiosInstance, type AxiosRequestConfig } from 'axios'
import { storage } from '@/utils'
import router from '@/router'

/**
 * @description: 校验网络请求状态码
 * @param {Number} status
 * @return void
 */
export const checkStatus = (status: number) => {
  switch (status) {
    case 400:
      window.$message.error('请求失败！请您稍后重试')
      break
    case 401:
      window.$message.error('登录失效！请您重新登录')
      break
    case 403:
      window.$message.error('当前账号无权限访问！')
      break
    case 404:
      window.$message.error('你所访问的资源不存在！')
      break
    case 405:
      window.$message.error('请求方式错误！请您稍后重试')
      break
    case 408:
      window.$message.error('请求超时！请您稍后重试')
      break
    case 500:
      window.$message.error('服务异常！')
      break
    case 502:
      window.$message.error('网关错误！')
      break
    case 503:
      window.$message.error('服务不可用！')
      break
    case 504:
      window.$message.error('网关超时！')
      break
    default:
      window.$message.error('请求失败！')
  }
}

const config: AxiosRequestConfig = {
  // 设置基准请求地址，可在 .env.** 文件中修改
  baseURL: import.meta.env.VITE_API_URL as string,
  // 设置超时时间
  timeout: 1000 * 10
}

class RequestHttp {
  service: AxiosInstance
  constructor(config: AxiosRequestConfig) {
    // 创建 axios 实例
    this.service = axios.create(config)

    /**
     * 请求拦截器
     * 客户端发送请求 -> [请求拦截器] -> 服务器
     */
    this.service.interceptors.request.use(
      (config) => {
        const token = storage.get('token')

        if (token) {
          config.headers.Authorization = token
        }
        return config
      },
      (error: AxiosError) => {
        return Promise.reject(error)
      }
    )

    /**
     * 响应拦截器
     * 服务端返回信息 -> [响应拦截器统一处理] -> 业务组件获取到信息
     */
    this.service.interceptors.response.use(
      (response) => {
        const result = response.data

        // 业务状态码校验
        if (result.code && result.code !== 1000) {
          window.$message.error(result.message)
          return Promise.reject(result)
        }

        return result.data
      },
      (error: AxiosError) => {
        const { response } = error
        // 请求超时 && 网络错误单独判断，没有 response
        if (error.message.includes('timeout')) window.$message.error('请求超时！请您稍后重试')
        if (error.message.includes('Network Error')) window.$message.error('网络错误！请您稍后重试')
        // 根据服务器响应的错误状态码，做不同的处理
        if (response) checkStatus(response.status)
        // 服务器结果都没有返回(可能服务器错误可能客户端断网)，断网处理:可以跳转到断网页面
        if (!window.navigator.onLine) router.replace('/500').finally()
        return Promise.reject(error)
      }
    )
  }

  get<T>(url: string, params?: object, _config = {}): Promise<T> {
    return this.service.get(url, { params, ..._config })
  }

  post<T>(url: string, params?: object, _config = {}): Promise<T> {
    return this.service.post(url, params, _config)
  }
}

export default new RequestHttp(config)
